package com.powerhousecreative.q;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.annotation.TargetApi;
import android.app.ActionBar;
import android.os.AsyncTask;
import android.os.Bundle;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

import android.os.Build;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;

import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;


public class MainActivity extends FragmentActivity implements ActionBar.OnNavigationListener {
	/**
	 * The serialization (saved instance state) Bundle key representing the
	 * current dropdown position.
	 */
	private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
	private ArrayList<Fragment>  mainFragments = new ArrayList<Fragment> ();
	private int fragmentIndex;
	private JSONObject youtubeDict;	

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// Set up the action bar to show a dropdown list.
		final ActionBar actionBar = getActionBar();
		actionBar.setDisplayShowTitleEnabled(false);
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

		// Set up the dropdown list navigation in the action bar.
		actionBar.setListNavigationCallbacks(
		// Specify a SpinnerAdapter to populate the dropdown list.
				new ArrayAdapter<String>(getActionBarThemedContextCompat(),
						android.R.layout.simple_list_item_2,
						android.R.id.text1, new String[] {
								getString(R.string.title_section1),
								getString(R.string.title_section2),
								getString(R.string.title_section3), 
								getString(R.string.title_section4),
								getString(R.string.title_section5), }), this);
		
		for (int i = 0 ; i < 5 ; i++) {
			mainFragments.add(new DummySectionFragment ());			
		}
	}
	
	public void setGridItems (JSONArray items) throws JSONException  {		
		Fragment fragment = new DummySectionFragment(new GridViewAdapter(this, R.layout.grid_cell, getData(items)));
		mainFragments.set(fragmentIndex, fragment);
		
		getSupportFragmentManager().beginTransaction()
				.replace(R.id.container, fragment).commit();
	}
	
	public void showDetailView (int index) throws JSONException {		
		//Log.d("Click", "id#" + index);
		
		JSONArray items = youtubeDict.getJSONArray("items");
		Intent i = new Intent(getApplicationContext(), YoutubeDetailActivity.class);
        i.putExtra("entry", items.getJSONObject(index).toString());
        startActivity(i);
	}
	
	private ArrayList<MainGridItem> getData(JSONArray items) throws JSONException {
		final ArrayList<MainGridItem> imageItems = new ArrayList<MainGridItem>();
		
		for (int i = 0 ; i < items.length() ; i++) {
    		imageItems.add(new MainGridItem(items.getJSONObject(i)));
    	}
		return imageItems;
	}

	/**
	 * Backward-compatible version of {@link ActionBar#getThemedContext()} that
	 * simply returns the {@link android.app.Activity} if
	 * <code>getThemedContext</code> is unavailable.
	 */
	@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
	private Context getActionBarThemedContextCompat() {
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
			return getActionBar().getThemedContext();
		} else {
			return this;
		}
	}

	@Override
	public void onRestoreInstanceState(Bundle savedInstanceState) {
		// Restore the previously serialized current dropdown position.
		if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
			getActionBar().setSelectedNavigationItem(
					savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
		}
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		// Serialize the current dropdown position.
		outState.putInt(STATE_SELECTED_NAVIGATION_ITEM, getActionBar()
				.getSelectedNavigationIndex());
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onNavigationItemSelected(int position, long id) {
		// When the given dropdown item is selected, show its contents in the
		// container view.
		fragmentIndex = position;
		
		Fragment fragment = mainFragments.get(position);
		Bundle args = new Bundle();
		args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, position + 1);
		fragment.setArguments(args);
		getSupportFragmentManager().beginTransaction()
				.replace(R.id.container, fragment).commit();
		return true;
	}	
	
	public void AccountLogin(View view) {
		Intent intent = new Intent(this, YoutubeLoginActivity.class);
		startActivity(intent);
	}
	
	public void AskForYoutubeChannel (View view) {
		SharedPreferences settings = getSharedPreferences(getString(R.string.perf_name), 0);
		String token = settings.getString(getString(R.string.Youtube_accessToken), "");
		Log.d ("access token", token);
		
		String requestUrl = "https://www.googleapis.com/youtube/v3/channels?part=contentDetails&mine=true&access_token=" + token;
		
		AsyncRequest request = new AsyncRequest (requestUrl, 0);
    	request.execute ();
	}
	
	public void AskForWatchLater(View view) {
		SharedPreferences settings = getSharedPreferences(getString(R.string.perf_name), 0);
		String token = settings.getString(getString(R.string.Youtube_accessToken), "");
		String id = settings.getString(getString(R.string.Youtube_watchLaterList), "");
		
		String requestUrl = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=10&playlistId=" + id + "&access_token=" + token;
		AsyncRequest request = new AsyncRequest (requestUrl, 1);
    	request.execute ();
	}
	
	public void refreshYoutubeToken (int mode) {
		SharedPreferences settings = getSharedPreferences(getString(R.string.perf_name), 0);
		String token = settings.getString(getString(R.string.Youtube_refreshToken), "");
		Log.d ("refresh token", token);
		
		YoutubeRefreshTokenRequest request = new YoutubeRefreshTokenRequest(token, mode);
		request.execute();
	}
	
	/** Private Classes:
	 * - AsyncRequest
	 * - YoutubeRefreshTokenRequest
	 */
	
	private class AsyncRequest extends AsyncTask<Void, Void, Void>{
	    private static final String TAG = "Request";    
	    private String requestUrl;
	    private int mode;
	    //private String accessToken;

	    public AsyncRequest(String url, int mode) {
	        this.requestUrl = url;
	        this.mode = mode;
	    }

	    @Override
	    protected Void doInBackground(Void... params) {
	      try {
	        fetchNameFromProfileServer();
	      } catch (IOException ex) {
	        onError("Following Error occured, please try again. " + ex.getMessage(), ex);
	      } catch (JSONException e) {
	        onError("Bad response: " + e.getMessage(), e);
	      }
	      return null;
	    }

	    protected void onError(String msg, Exception e) {
	        if (e != null) {
	          Log.e(TAG, "Exception: ", e);
	        }
	    }
	    
	    private void fetchNameFromProfileServer() throws IOException, JSONException {	    	
	    	URL url = new URL(requestUrl);
	    	HttpURLConnection con = (HttpURLConnection) url.openConnection();
	        //con.setRequestMethod("GET");
	        //con.setRequestProperty ("Authorization", "Bearer " + accessToken);
	        
	        int sc = con.getResponseCode();
	        if (sc == 200) {
	        	InputStream is = con.getInputStream();
	        	
	        	if (mode == 0) {
	        		getChannelList (readResponse(is));	        		
	        	}
	        	else if (mode == 1) {
	        		getYoutubeDict (readResponse(is));
	        	}

	        	is.close();
	        	return;
	        } else if (sc == 401) {
	            onError("Access Token is expired, refresh the token.", null);
	            Log.i(TAG, "Server auth error: " + readResponse(con.getErrorStream()));
	            
	            refreshYoutubeToken (mode);
	            return;
	        } else {
	        	onError("Server returned the following error code: " + sc, null);
	        	Log.i(TAG, "Server auth error: " + readResponse(con.getErrorStream()));
	        	return;
	        }
	    }
	    
	    private String readResponse(InputStream is) throws IOException {
	        ByteArrayOutputStream bos = new ByteArrayOutputStream();
	        byte[] data = new byte[2048];
	        int len = 0;
	        while ((len = is.read(data, 0, data.length)) >= 0) {
	            bos.write(data, 0, len);
	        }
	        return new String(bos.toByteArray(), "UTF-8");
	    }
	    
	    private void getChannelList (String jsonResponse) throws JSONException {
	    	Log.d("Response", jsonResponse);
	    	
	    	JSONObject dict = new JSONObject(jsonResponse);
	    	JSONArray items = dict.getJSONArray("items");
	    	
	    	JSONObject item = items.getJSONObject(0).getJSONObject("contentDetails").getJSONObject("relatedPlaylists");    	
	    	Log.d ("Likes", item.getString("likes"));
	    	Log.d ("Favorites", item.getString("favorites"));
	    	Log.d ("Uploads", item.getString("uploads"));
	    	Log.d ("History", item.getString("watchHistory"));
	    	Log.d ("WatchLater", item.getString("watchLater"));
	    	
	    	SharedPreferences settings = getSharedPreferences(getString(R.string.perf_name), 0);
			SharedPreferences.Editor editor = settings.edit();
			editor.putString(getString(R.string.Youtube_favoritesList), item.getString("favorites"));
			editor.putString(getString(R.string.Youtube_historyList), item.getString("watchHistory"));
			editor.putString(getString(R.string.Youtube_watchLaterList), item.getString("watchLater"));
			editor.commit();
	    }
	    
	    private void getYoutubeDict (String jsonResponse) throws JSONException {
	    	Log.d("Response", jsonResponse);
	    	
	    	youtubeDict = new JSONObject(jsonResponse);
	    	JSONArray items = youtubeDict.getJSONArray("items");
	    	
	    	setGridItems (items);
	    }
	}
	
	private class YoutubeRefreshTokenRequest extends AsyncTask<Void, Void, Void>{
		private static final String CLIENT_ID = "604076768569.apps.googleusercontent.com";
		private static final String CLIENT_SECRET = "EEqDJ0jCdQ4LvZfDockZUpos";
		
	    private static final String TAG = "Request";    
	    private String requestUrl = "https://accounts.google.com/o/oauth2/token";
	    private String refreshToken;
	    private int mode;

	    public YoutubeRefreshTokenRequest(String token, int mode) {
	        this.refreshToken = token;
	        this.mode = mode;
	    }

	    @Override
	    protected Void doInBackground(Void... params) {
	      try {
	    	  fetchAccessTokenByRefreshToken();
	      } catch (IOException ex) {
	        onError("Following Error occured, please try again. " + ex.getMessage(), ex);
	      } catch (JSONException e) {
	        onError("Bad response: " + e.getMessage(), e);
	      }
	      return null;
	    }

	    protected void onError(String msg, Exception e) {
	        if (e != null) {
	          Log.e(TAG, "Exception: ", e);
	        }
	        //mActivity.show(msg);  // will be run in UI thread
	    }

	    private void fetchAccessTokenByRefreshToken() throws IOException, JSONException { 	    	
	        HttpClient httpclient = new DefaultHttpClient();
	        HttpPost httppost = new HttpPost(requestUrl);
	        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(4);
	        nameValuePairs.add(new BasicNameValuePair("client_id", CLIENT_ID));
	        nameValuePairs.add(new BasicNameValuePair("client_secret", CLIENT_SECRET ));
	        nameValuePairs.add(new BasicNameValuePair("refresh_token", refreshToken));
	        nameValuePairs.add(new BasicNameValuePair("grant_type", "refresh_token"));
	        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

	        // Execute HTTP Post Request
	        HttpResponse response = httpclient.execute(httppost);

	        String ret = EntityUtils.toString(response.getEntity());
	        Log.d("Response", ret);
	        
	        fetchAccessToken (ret);
	    }
	    
	    private void fetchAccessToken (String jsonResponse) throws JSONException {
	    	JSONObject dict = new JSONObject(jsonResponse);
	    	
	    	SharedPreferences settings = getSharedPreferences(getString(R.string.perf_name), 0);
			SharedPreferences.Editor editor = settings.edit();
			editor.putString(getString(R.string.Youtube_accessToken), dict.getString("access_token"));
			
			editor.commit();
			
			if (mode == 0) {
				AskForYoutubeChannel (null);
			}
			else if (mode == 1) {
				AskForWatchLater(null);
			}
	    }
	    
	}

}
